"""
Auto-gerador de classes e propriedades

$Id: autogen.py 2 2007-03-04 19:08:44Z sidnei.da.silva $
"""

class field:
    def __init__(self, name):
        self.__name__ = name

    def getName(self):
        return self.__name__

class generator(type):
    def __init__(cls, name, bases, dict):
        super(autoprop, cls).__init__(name, bases, dict)
        props = {}
        for item in dict.values():
            if isinstance(item, field):
               name = item.getName()
               generator.generateAccessor(cls, name)
               generator.generateMutator(cls, name)

    def generateAccessor(cls, name):
        method = lambda self, name=name: \
                 getattr(self, name)
        methodName = "get%s" % name.capitalize()
        setattr(cls, methodName, method)

    def generateMutator(cls, name):
        method = lambda self, value, name=name: \
                 setattr(self, name, value)
        methodName = "set%s" % name.capitalize()
        setattr(cls, methodName, method)

class autoprop(type):
    def __init__(cls, name, bases, dict):
        super(autoprop, cls).__init__(name, bases, dict)
        props = {}
        for item in dict.values():
            if isinstance(item, field):
               name = item.getName()
               props[name] = 1
        for name in props.keys():
            fget = getattr(cls, "get%s"% name.capitalize(), None)
            fset = getattr(cls, "set%s"% name.capitalize(), None)
            setattr(cls, name, property(fget, fset))

class autogen(generator, autoprop):
     pass

class MyClass:
     __metaclass__ = autogen

     firstname = field('firstname')
     lastname  = field('lastname')

import unittest

class TestAutogen(unittest.TestCase):

    def setUp(self):
        self.m = MyClass()

    def testMutators(self):
        self.failUnless(hasattr(MyClass, 'setFirstname'))
        self.failUnless(hasattr(MyClass, 'setLastname'))

    def testProperties(self):
        self.failUnless(hasattr(MyClass, 'firstname'))
        self.failUnless(hasattr(MyClass, 'lastname'))
        self.failUnless(hasattr(self.m, 'firstname'))
        self.failUnless(hasattr(self.m, 'lastname'))
        self.failUnless(isinstance(MyClass.firstname, field))
        self.failUnless(isinstance(MyClass.lastname, field))
        self.failUnless(isinstance(self.m.firstname, field))
        self.failUnless(isinstance(self.m.lastname, field))

    def testFirstname1(self):
        self.m.setFirstname('Sidnei')
        self.assertEquals(self.m.getFirstname(), 'Sidnei')
        self.assertEquals(self.m.firstname, 'Sidnei')

    def testFirstname2(self):
        self.m.firstname = 'Daiane'
        self.assertEquals(self.m.getFirstname(), 'Daiane')
        self.assertEquals(self.m.firstname, 'Daiane')

    def testLastname1(self):
        self.m.setLastname('Silva')
        self.assertEquals(self.m.getLastname(), 'Silva')
        self.assertEquals(self.m.lastname, 'Silva')

    def testLastname2(self):
        self.m.lastname = 'da Silva'
        self.assertEquals(self.m.getLastname(), 'da Silva')
        self.assertEquals(self.m.lastname, 'da Silva')

def test_suite():
    return unittest.TestSuite((
        unittest.makeSuite(TestAutogen),
        ))

if __name__ == '__main__':
    unittest.main()
